package jam4j;

import jam4j.lang.SpecialVariable;

import java.util.HashMap;
import java.util.Map;

/**
 * Any of the operating systems recognized by Jam4J. Each defines certain
 * parameters, including the value of the OS special variable.
 * 
 * @see SpecialVariable#OS
 * 
 * @author Luke Maurer
 */
public enum OperatingSystem {
    VMS("VMS", 1024),
    NT("NT", 996, "Windows NT", "Windows 2000", "Windows XP", "Windows 2003"),
    AS400("AS400", 996),
    MINGW("MINGW", 996),
    OS2("OS2", 996, "OS/2"),
    MAC("MAC", "Mac OS"),
    AIX("UNIX", "AIX"),
    AMIGA("UNIX"),
    BEOS("UNIX"),
    BSDI("UNIX"),
    COHERENT("UNIX"),
    CYGWIN("UNIX"),
    FREEBSD("UNIX", "FreeBSD"),
    DGUX("UNIX", "Digital Unix"),
    HPUX("UNIX", "HP-UX"),
    INTERIX("UNIX"),
    IRIX("UNIX", "Irix"),
    ISC("UNIX"),
    LINUX("UNIX", "Linux"),
    LYNX("UNIX"),
    MACHTEN("UNIX"),
    MPEIX("UNIX", "MPE/iX"),
    MVS("UNIX"),
    NCR("UNIX"),
    NETBSD("UNIX"),
    QNXNTO("UNIX"),
    QNX("UNIX", 996),
    RHAPSODY("UNIX"),
    NEXT("UNIX"),
    MACOSX("UNIX", "Mac OS X"),
    OSF("UNIX", "OSF1"),
    PTX("UNIX"),
    SCO("UNIX"),
    SINIX("UNIX"),
    SOLARIS("UNIX", "Solaris"),
    SUNOS("UNIX", "SunOS"),
    ULTRIX("UNIX"),
    UNICOS("UNIX"),
    UNIXWARE("UNIX"),
    UNKNOWN("UNIX")
    ;
    
    private final String flagName;
    private final int commandLineMaximum;
    private final String[] javaNames;
    
    private OperatingSystem(String flagName, int commandLineMaximum,
            String ... javaNames) {
        this.flagName = flagName;
        this.commandLineMaximum = commandLineMaximum;
        this.javaNames = javaNames;
    }
    
    private OperatingSystem(String flagName, String ... javaNames) {
        this(flagName, 10240, javaNames);
    }
    
    /**
     * @return The name of the variable to set to {@code 1} to indicate the
     * running platform.
     */
    public String flagName() {
        return flagName == null ? name() : flagName;
    }
    
    /**
     * @return The number of characters the command line can handle on this
     * platform.
     */
    public int commandLineMaximum() {
        return commandLineMaximum;
    }
    
    private static final Map<String, OperatingSystem> JAVA_NAME_MAP;
    
    static {
        JAVA_NAME_MAP = new HashMap<String, OperatingSystem>();
        for (OperatingSystem os : values())
            for (String javaName : os.javaNames)
                JAVA_NAME_MAP.put(javaName, os);
    }
        
    /**
     * @return The operating system which is running Jam4J. This is used to
     * set the {@code OS} variable.
     * 
     * @see SpecialVariable#OS
     */
    public static OperatingSystem hostSystem() {
        final String javaName = System.getProperty("os.name");
        if (JAVA_NAME_MAP.containsKey(javaName))
            return JAVA_NAME_MAP.get(javaName);
        return UNKNOWN;
    }
    
    public final boolean needsNTStyleExec() {
        return this == OS2 || this == NT;
    }
}
